package cn.com.ethos.search.index;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Properties;

import org.apache.commons.cli.MissingOptionException;
import org.apache.log4j.Logger;
import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.analysis.standard.StandardAnalyzer;
import org.apache.lucene.store.FSDirectory;

import cn.com.ethos.search.DbSetting;
import cn.com.ethos.search.ParametersHelper;
import cn.com.ethos.search.drupal.CommentStream;
import cn.com.ethos.search.drupal.NodeStream;

/**
 * need open files : (1 + mergeFactor) * FilesPerSegment
 * 
 * @author gaoxinzhao@ethos.com.cn
 */
public class IndexFacade {

	/**
	 * key in properties file : index.dir
	 */
	public static final String DIR_PATH_KEY      = "index.dir";
	
	public static final String MERGE_FACTOR      = "index.merge.factor";
	
	public static final String MAX_BUFFER_DOCS   = "index.max.buffer.docs";
	
	public static final String MAX_MERGE_DOCS    = "index.max.merge.docs";
	
	public static final String USE_COMPOUND_FILE = "index.use.compound.file";
	
	private static final Logger logger = Logger.getLogger(IndexFacade.class);
	
	public static void optimize(Properties prop) 
			throws FileNotFoundException,IOException {
		
		Analyzer analyzer   = new StandardAnalyzer();
		IndexServer indexer = new IndexServer(FSDirectory.getDirectory(prop.getProperty(DIR_PATH_KEY)),analyzer,false);
		indexer.optimize();
	}
	
	public static void index(Properties prop,Analyzer analyzer) 
			throws FileNotFoundException,IOException,MissingOptionException {
		
		String  path   = prop.getProperty(DIR_PATH_KEY);
		boolean create = !new File(path).isDirectory();
		if(!create) {
			logger.info("Creating Index Writer,the directory alreadly exists, the document will be add this index." + path + ", \r\n if it is not an index directory or if you want to create a new index directory or there will be an error,please remove this directory.");
		} else {
			logger.info("Creating Index Writer,the directory will be create from " + path);
		}
		index(prop,analyzer,create);
	}
	
	public static void index(Properties prop,Analyzer analyzer,boolean create) 
			throws FileNotFoundException,IOException,MissingOptionException{
		
		DbSetting setting  = new DbSetting(prop);
		Select[] list = Select.createFromProperties(prop);
		ArrayList<IDocumentStream> docStreamList = new ArrayList<IDocumentStream>();
		for(Select sel : list) {
			sel.setBuildParamters(ParametersHelper.getParamHashMap());
			docStreamList.add(new GenericDbRowStream(setting,sel));
		}
		
		String  path  = prop.getProperty(DIR_PATH_KEY);
		File    file  = new File(path); 
		if(create && file.exists()) {
			file.delete();
		}
		
		IndexServer indexer = new IndexServer(FSDirectory.getDirectory(path),analyzer,create);		
		if(prop.containsKey(MAX_MERGE_DOCS)) {
			int value = Integer.parseInt(prop.getProperty(MAX_MERGE_DOCS));
			indexer.setMaxMergeDocsNum(value);
		}
		if(prop.containsKey(MAX_BUFFER_DOCS)) {
			int value = Integer.parseInt(prop.getProperty(MAX_BUFFER_DOCS));
			indexer.setMaxBufferDocsNum(value);
		}
		if(prop.containsKey(MERGE_FACTOR)) {
			int value = Integer.parseInt(prop.getProperty(MERGE_FACTOR));
			indexer.setMergeFactorNum(value);
		}
		if(prop.containsKey(USE_COMPOUND_FILE)) {
			logger.debug("use compound file key : " + USE_COMPOUND_FILE);
			logger.debug("the value is :");
			logger.debug(prop.getProperty(USE_COMPOUND_FILE));
			
			boolean value = Boolean.valueOf(prop.getProperty(USE_COMPOUND_FILE));
			indexer.setUseCompoundFile(value);
		}
		
		indexer.start(docStreamList.toArray(new IDocumentStream[0]));		
	}
	
	public static void delete(Properties prop,Analyzer analyzer,String file) {
		InputStream stream = null;
		
		if(null != file && !file.isEmpty()) {
			try {
				stream = new FileInputStream(file);
			}catch(IOException ex) {
				logger.warn("loading file from " + file + " failed" );
			}
		}		
		if(null == stream) {
			stream = System.in;
		}
		
		String  path  = prop.getProperty(DIR_PATH_KEY);
		IndexServer indexer = null;
		
		try {
			indexer = new IndexServer(FSDirectory.getDirectory(path),analyzer,false);
		}catch(IOException ex) {
			logger.error("Initializing indexer failed",ex);
			System.exit(1);
		}
		
		try {
			indexer.delete(stream);
		}catch(Exception ex) {
			logger.error("Error occured when delete document",ex);
			System.exit(1);
		}
	}
	
	/**
	 * @deprecated with GenericDbRowStream instead of NodeStream and CommentStrean,so use index(Properties prop,Analyzer analyzer) 
	 * @param path
	 * @throws FileNotFoundException
	 * @throws IOException
	 */
	public static void index(String path) throws FileNotFoundException,IOException {
		Properties prop = new Properties();
		prop.load(new FileInputStream(path));
		
		DbSetting setting  = new DbSetting(prop);
		IDocumentStream[] docStreamList = new IDocumentStream[]{
				new NodeStream(setting),
				new CommentStream(setting)
		};
		String dir = prop.getProperty(DIR_PATH_KEY);
		IndexServer indexer = new IndexServer(FSDirectory.getDirectory(dir),new StandardAnalyzer(),!new File(dir).isDirectory());
		indexer.start(docStreamList);
	}

}
